/* LEDC (LED Controller) fade example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "esp_err.h"
#include "esp_mac.h"
#include "esp_log.h"

#include "driver/adc.h"
#include "driver/gpio.h"
#include "my_adc_drv.h"
#include "my_ntc_drv.h"

const static char *TAG = "ntc_drv";

#define MAX_ADC_READ_CNT    (20)
static int ntc_adc_data[MAX_ADC_READ_CNT] ={0};

typedef struct 
{
    int adc;        // adc值
    float resis;    // 电阻值
    float temp;
}ntc_param_t;

typedef struct 
{
    ntc_param_t ntc1;
    ntc_param_t ntc2;   // 第二个ntc扩展/预留
}ntc_data_t;



ntc_data_t ntc_data;


/**************************************************************************************
* FunctionName   : BubbleSort()
* Description    :
* EntryParameter : 冒泡排序法
* Description    : --
* ReturnValue    :
**************************************************************************************/
void BubbleSort(int *arr, int size)  
{  
    int i, j, tmp;  
    int swap_times = 0;
    
    for (i = 0; i < size - 1; i++) 
    {  
        for (j = 0; j < size - i - 1; j++) 
        {  
            if (arr[j] > arr[j+1]) 
            {  
                //printf("_02 swap_cnt:%d [%d]:%d <--->[%d]:%d \r\n",swap_times, j, arr[j], j+1, arr[j + 1]);
                tmp = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = tmp; 
                swap_times ++; 
            }
        }  
    }
    // printf(" \r\n bubble_sort_02 swap_times:%d \r\n", swap_times);
}  
/**************************************************************************************
* FunctionName   : Get_Temp()
* Description    :
*               Rt ： 当前的电阻值，（欧姆为单位）
*               Rp ： 25°C时电阻值如10k时（10000）（欧姆为单位）
*               Bx ： b值 如（3380）
* EntryParameter :
* Description    : --
* ReturnValue    :
**************************************************************************************/
const float Ka = 273.15;
const float T2 = (273.15 + 25.0);//T2
float Get_Temp(float Rt, float Rp, float Bx)
{
    float temp;
    temp = Rt / Rp;
    temp = log(temp);
    temp /= Bx;
    temp += (1/T2);
    temp = 1/(temp);
    temp -= Ka;
    return temp;
}

/*************************************************************************************
* FunctionName   : 电阻特性：3.3v --10k ---NTC--GND
* Description    :  2.5V --4096
* EntryParameter :
* ReturnValue    : None
**************************************************************************************/
static float ntc_resistance_use_adc(int adc_val)
{
    int ret;
    int tmp;

    // 1. 当前测试点的实际电压
    tmp = adc_val * 2500 / 4096; //单位是mV

    // 2. 当前电阻
    // 3300/（10000 +r)） = tmp/ r)
    ret = 10000 * tmp / (3300 - tmp);
    return ret;
}

/*************************************************************************************
* FunctionName   : 电阻特性：3.3v --100k ---NTC--GND
* Description    :  2.5V --4096
* EntryParameter :
* ReturnValue    : None
**************************************************************************************/
static float ntc_resistance_use_vol(int bat_data)
{
    return 100000 * bat_data / (3300 - bat_data);
}

/*************************************************************************************
* FunctionName   : 电阻特性： 100k 型号3950
* Description    :
* EntryParameter :
* ReturnValue    : None
**************************************************************************************/
void my_ntc_read(void)
{
    static int read_adc_cnt = 0;

    ntc_adc_data[read_adc_cnt%MAX_ADC_READ_CNT]= single_read();

    if(read_adc_cnt%MAX_ADC_READ_CNT == (MAX_ADC_READ_CNT - 1)){
        BubbleSort(ntc_adc_data, MAX_ADC_READ_CNT);

        ntc_data.ntc1.resis = ntc_resistance_use_vol(ntc_adc_data[MAX_ADC_READ_CNT/2]);
        ntc_data.ntc1.temp = Get_Temp(ntc_data.ntc1.resis, 100000, 3950) - 1;
        ESP_LOGI(TAG, "vol:[%d], resis[%.2f]Ω, temp:[%.2f]°C ", ntc_adc_data[MAX_ADC_READ_CNT/2], ntc_data.ntc1.resis, ntc_data.ntc1.temp);
    }
    read_adc_cnt ++;
}


/*************************************************************************************
* FunctionName   : 对外输出 温度
* Description    :
* EntryParameter :
* ReturnValue    : None
**************************************************************************************/
float get_ntc_temperature(void)
{
    return ntc_data.ntc1.temp;
}


/**************************************************
 * 
 * ntc 任务
 **************************************************/
static void get_ntc_value_task(void *arg)
{
    for (;;) {
        my_ntc_read();
        vTaskDelay(pdMS_TO_TICKS(100));
    }
    vTaskDelete(NULL);
}

/**************************************************
 * 
 * 初始化
 **************************************************/
void my_ntc_init(void)
{
    int ret = 0;

    ret = xTaskCreate(get_ntc_value_task, "get_ntc_value", 4096, NULL, 15, NULL);
    if(ret == 0){
        ESP_LOGE(TAG, " creat ntc_task err!!");
    }
    else{
        ESP_LOGI(TAG, " creat ntc_task succ");
    }
}